﻿using Cofe.Core.Implements;
using Cofe.Core.Interfaces;
using Cofe.Core.Security;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
#if NETFX_CORE
using Windows.Storage;
#else

#endif
namespace Cofe.Core.Session
{
    [Export(typeof(ICofeService))]
    [ServicePriority(ServicePriorityAttribute.DefaultPriority_COFE)]
    public class CofeSettings : ICofeSettings
    {
        #region Constructor

        public CofeSettings(ISuspensionManager suspensionManager)
        {            
            _suspensionManager = suspensionManager;
            _suspensionManager.KnownTypes = _knownTypes;
        }


        public CofeSettings()
#if NETFX_CORE
            : this(new WinRT_SuspensionManager())
#else 
            : this(new IsolatedStorage_SuspensionManager())
#endif
        {

        }

        #endregion

        #region Methods

        //Taken from BingImageSearch sample.
        private bool _isSaving;
        public async virtual Task SaveAsync()
        {
            if (_isSaving) return;
            _isSaving = true;
            await _suspensionManager.SaveAsync();
            _isSaving = false;
            Saved(this, EventArgs.Empty);
        }

        public async virtual Task RestoreAsync()
        {
            await _suspensionManager.RestoreAsync();
        }

        protected T GetOrDefault<T>(string key, T @default = default(T))
        {
            if (_suspensionManager.SessionState.ContainsKey(key))
            {
                return (T)_suspensionManager.SessionState[key];
            }
            return @default;
        }

        protected T GetOrNew<T>(string key) where T : class, new()
        {
            //if (!(_suspensionManager.SessionState.ContainsKey(key)))
            //{
            //    _suspensionManager.SessionState[key] = new T();
            //}
            //return (T)_suspensionManager.SessionState[key];

            if (_suspensionManager.SessionState.ContainsKey(key))
            {
                return (T)_suspensionManager.SessionState[key];
            }
            return new T();
        }

        protected void SaveOrCreate<T>(string key, T value)
        {
            if (_suspensionManager.SessionState.ContainsKey(key))
            {
                _suspensionManager.SessionState[key] = value;
            }
            else
            {
                _suspensionManager.SessionState.Add(key, value);
            }
        }

        public IEnumerable<IPermissionPolicy<T>> GetPermissionPolicies<T>() where T : IProtectedData<T>
        {
            return from p in Permissions
                   where p is IPermissionPolicy<T>
                   select p as IPermissionPolicy<T>;
        }

        #endregion

        #region Data

        private readonly ISuspensionManager _suspensionManager;        

        private List<Type> _knownTypes = new List<Type>() 
            {                 
                typeof(Dictionary<string, object>),
                typeof(Dictionary<int, string>),
                typeof(string),
                typeof(DateTime),
                typeof(TimeSpan),
                
                typeof(VolumeInfo),                
                typeof(VolumeInfoList),                                  
                typeof(GenericPrincipalPolicy),
                typeof(UserPolicyList),   

                typeof(VolumePermissionPolicy),                
                typeof(PermissionList),
                typeof(CacheUpdateOptions)
                   
            };

        #endregion

        #region Public Properties

        public UserPolicyList UserPermissions
        {
            get { return GetOrNew<UserPolicyList>("UserPermissions"); }            
            set { SaveOrCreate("UserPermissions", value); }
        }

        public VolumeInfoList Volumes
        {
            get { return GetOrNew<VolumeInfoList>("Volumes"); }
            set { SaveOrCreate("Volumes", value); }
        }

        public PermissionList Permissions
        {
            get { return GetOrNew<PermissionList>("VolumePermissions"); }
            set { SaveOrCreate("VolumePermissions", value); }
        }

        public TimeSpan CacheExpireTime
        {
            get { return GetOrDefault<TimeSpan>("CacheExprireTime", TimeSpan.FromDays(90)); }
            set { SaveOrCreate("CacheExprireTime", value); }
        }

        public TimeSpan ListExpireTime
        {
            get { return GetOrDefault<TimeSpan>("ListExpireTime", TimeSpan.FromDays(45)); }
            set { SaveOrCreate("ListExpireTime", value); }
        }


        public TimeSpan EventBufferTime
        {
            get { return GetOrDefault<TimeSpan>("EventBufferTime", TimeSpan.FromSeconds(5)); }
            set { SaveOrCreate("EventBufferTime", value); }
        }

        public CacheUpdateOptions CacheUpdateOptions
        {
            get { return GetOrDefault<CacheUpdateOptions>("CacheUpdateOptions", CacheUpdateOptions.Passive); }
            set { SaveOrCreate("CacheUpdateOptions", value); }
        }

        public event EventHandler Saved = delegate { };

        #endregion








    }



}
